package com.kaifamiao.object;

import java.util.Objects;

public class People {

    private String fullName;
    private char gender;
    private int age;

    public People(String name, char gender, int age) {
        this.fullName = name;
        this.gender = gender;
        this.age = age;
    }

    // getName() ==> 去除get和参数部分 ==> Name ==> 首字母变小写 ==> name
    public String getName() {
        return fullName;
    }

    // setName(String) ==> 去除set和参数部分 ==> Name ==> 首字母变小写 ==> name
    public void setName(String fullName) {
        this.fullName = fullName;
    }

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals( Object another ) {
        if( another == null) {
            return false;
        }

        if( this == another ) {
            return true;
        }

        // JDK 16 之前用法是 "t instanceof T"
        // 翻译成人话就是 "t所指向的对象(实例) 是 T类型 吗?" 若是就返回 true 否则返回 false
        // 如果 "引用变量 another 所指向的对象(实例) 是 People类型"
        if( another instanceof People ) {
            // 将 another 强制类型转换为 People 类型
            People x = (People) another;
            // 比较当前对象和另一个对象的 fullName 、gender 、age 等实例变量的值是否相等
            return fullName != null && fullName.equals(x.fullName) && gender == x.gender && age == x.age;
        }

        return false;
    }

    @Override
    public int hashCode() {
        int result = 1;
        // 为什么这里是31呢？？？
        result = 31 * result + (fullName == null ? 0 : fullName.hashCode());
        result = 31 * result + gender;
        result = 31 * result + age;
        return result;
    }

    @Override
    public String toString() {
        String description = String.format("People { name: %s, gender: %c, age: %d }", fullName, gender, age );
        return description;
    }

    public static void main(String[] args) {
        People p = null;
        System.out.println( p ); // p == null ? "null" : p.toString()

        p = new People( "王勃", '男' , 22 );
        System.out.println( p ); // p == null ? "null" : p.toString()

        // hashCode常规协定一:
        // 在 Java 应用程序执行期间，在对同一对象多次调用 hashCode 方法时，必须一致地返回相同的整数，
        // 前提是将对象进行 equals 比较时所用的信息没有被修改
        System.out.println( "hash code value: " + p.hashCode() );
        System.out.println( "hash code value: " + p.hashCode() );

        p.setName( "李清照" );
        p.setGender( '女' );
        p.setAge( 30 );
        // 如果将 equals 中比较时使用的 信息予以修改，则会导致产生新的 哈希码值
        System.out.println( "hash code value: " + p.hashCode() );
        System.out.println( "hash code value: " + p.hashCode() );

        People e = new People( "李清照" , '女', 30 );
        System.out.println( p.equals( e ) ); // true
        System.out.println( e.equals( p ) ); // true
        // hashCode常规协定二:
        // 如果根据 equals(Object) 方法，两个对象是相等的，
        // 那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果
        System.out.println( p.hashCode() == e.hashCode() ); // true

        // 既然 People 类已经重写了从 Object 继承的 hashCode 方法，
        // 那么我们应该如何获得原本由 Object 的 hashCode 所返回的那个整数？
    }

}
